﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using IPC.Communication.BasicFramework;
using IPC.Communication.Core;
using IPC.Communication.Core.Address;

namespace IPC.Communication.Profinet.Omron
{
    public class OmronFinsNetHelper
    {
        public static OperateResult<List<byte[]>> BuildReadCommand(string address, ushort length, bool isBit, int splitLength = 500)
        {
            OperateResult<OmronFinsAddress> operateResult = OmronFinsAddress.ParseFrom(address, length);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<List<byte[]>>(operateResult);
            }
            List<byte[]> list = new List<byte[]>();
            int[] array = SoftBasic.SplitIntegerToArray(length, isBit ? int.MaxValue : splitLength);
            for (int i = 0; i < array.Length; i++)
            {
                byte[] array2 = new byte[8]
			{
				1,
				1,
				0,
				0,
				0,
				0,
				0,
				0
			};
                if (isBit)
                {
                    array2[2] = operateResult.Content.BitCode;
                }
                else
                {
                    array2[2] = operateResult.Content.WordCode;
                }
                array2[3] = (byte)(operateResult.Content.AddressStart / 16 / 256);
                array2[4] = (byte)(operateResult.Content.AddressStart / 16 % 256);
                array2[5] = (byte)(operateResult.Content.AddressStart % 16);
                array2[6] = (byte)(array[i] / 256);
                array2[7] = (byte)(array[i] % 256);
                list.Add(array2);
                operateResult.Content.AddressStart += (isBit ? array[i] : (array[i] * 16));
            }
            return OperateResult.CreateSuccessResult(list);
        }

        public static OperateResult<byte[]> BuildWriteWordCommand(string address, byte[] value, bool isBit)
        {
            OperateResult<OmronFinsAddress> operateResult = OmronFinsAddress.ParseFrom(address, 0);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult);
            }
            byte[] array = new byte[8 + value.Length];
            array[0] = 1;
            array[1] = 2;
            if (isBit)
            {
                array[2] = operateResult.Content.BitCode;
            }
            else
            {
                array[2] = operateResult.Content.WordCode;
            }
            array[3] = (byte)(operateResult.Content.AddressStart / 16 / 256);
            array[4] = (byte)(operateResult.Content.AddressStart / 16 % 256);
            array[5] = (byte)(operateResult.Content.AddressStart % 16);
            if (isBit)
            {
                array[6] = (byte)(value.Length / 256);
                array[7] = (byte)(value.Length % 256);
            }
            else
            {
                array[6] = (byte)(value.Length / 2 / 256);
                array[7] = (byte)(value.Length / 2 % 256);
            }
            value.CopyTo(array, 8);
            return OperateResult.CreateSuccessResult(array);
        }

        public static OperateResult<byte[]> ResponseValidAnalysis(byte[] response)
        {
            if (response.Length >= 16)
            {
                int num = BitConverter.ToInt32(new byte[4]
			{
				response[15],
				response[14],
				response[13],
				response[12]
			}, 0);
                if (num > 0)
                {
                    return new OperateResult<byte[]>(num, GetStatusDescription(num));
                }
                return UdpResponseValidAnalysis(response.RemoveBegin(16));
            }
            return new OperateResult<byte[]>(StringResources.Language.OmronReceiveDataError);
        }

        public static OperateResult<byte[]> UdpResponseValidAnalysis(byte[] response)
        {
            if (response.Length >= 14)
            {
                int num = response[12] * 256 + response[13];
                if (((response[10] == 1) & (response[11] == 1)) || ((response[10] == 1) & (response[11] == 4)) || ((response[10] == 2) & (response[11] == 1)) || ((response[10] == 3) & (response[11] == 6)) || ((response[10] == 5) & (response[11] == 1)) || ((response[10] == 5) & (response[11] == 2)) || ((response[10] == 6) & (response[11] == 1)) || ((response[10] == 6) & (response[11] == 32)) || ((response[10] == 7) & (response[11] == 1)) || ((response[10] == 9) & (response[11] == 32)) || ((response[10] == 33) & (response[11] == 2)) || ((response[10] == 34) & (response[11] == 2)))
                {
                    byte[] array = new byte[response.Length - 14];
                    if (array.Length != 0)
                    {
                        Array.Copy(response, 14, array, 0, array.Length);
                    }
                    OperateResult<byte[]> operateResult = OperateResult.CreateSuccessResult(array);
                    if (array.Length == 0)
                    {
                        operateResult.IsSuccess = false;
                    }
                    operateResult.ErrorCode = num;
                    operateResult.Message = GetStatusDescription(num) + " Received:" + SoftBasic.ByteToHexString(response, ' ');
                    return operateResult;
                }
                OperateResult<byte[]> operateResult2 = OperateResult.CreateSuccessResult(new byte[0]);
                operateResult2.ErrorCode = num;
                operateResult2.Message = GetStatusDescription(num) + " Received:" + SoftBasic.ByteToHexString(response, ' ');
                return operateResult2;
            }
            return new OperateResult<byte[]>(StringResources.Language.OmronReceiveDataError);
        }

        public static string GetStatusDescription(int err)
        {
            switch (err)
            {
                case 0:
                    return StringResources.Language.OmronStatus0;
                case 1:
                    return StringResources.Language.OmronStatus1;
                case 2:
                    return StringResources.Language.OmronStatus2;
                case 3:
                    return StringResources.Language.OmronStatus3;
                case 32:
                    return StringResources.Language.OmronStatus20;
                case 33:
                    return StringResources.Language.OmronStatus21;
                case 34:
                    return StringResources.Language.OmronStatus22;
                case 35:
                    return StringResources.Language.OmronStatus23;
                case 36:
                    return StringResources.Language.OmronStatus24;
                case 37:
                    return StringResources.Language.OmronStatus25;
                default:
                    return StringResources.Language.UnknownError;
            }
        }

        public static OperateResult<byte[]> Read(IReadWriteDevice omron, string address, ushort length, int splits)
        {
            bool isBit = false;
            OperateResult<List<byte[]>> operateResult = BuildReadCommand(address, length, isBit = false, splits);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult);
            }
            List<byte> list = new List<byte>();
            for (int i = 0; i < operateResult.Content.Count; i++)
            {
                OperateResult<byte[]> operateResult2 = omron.ReadFromCoreServer(operateResult.Content[i]);
                if (!operateResult2.IsSuccess)
                {
                    return OperateResult.CreateFailedResult<byte[]>(operateResult2);
                }
                list.AddRange(operateResult2.Content);
            }
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        public static OperateResult Write(IReadWriteDevice omron, string address, byte[] value)
        {
            OperateResult<byte[]> operateResult = BuildWriteWordCommand(address, value, isBit: false);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = omron.ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return OperateResult.CreateSuccessResult();
        }

        //[AsyncStateMachine(typeof(<ReadAsync>d__7))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<byte[]>> ReadAsync(IReadWriteDevice omron, string address, ushort length, int splits)
        //{
        //    <ReadAsync>d__7 stateMachine = new <ReadAsync>d__7();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.splits = splits;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__8))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IReadWriteDevice omron, string address, byte[] value)
        //{
        //    <WriteAsync>d__8 stateMachine = new <WriteAsync>d__8();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult<bool[]> ReadBool(IReadWriteDevice omron, string address, ushort length, int splits)
        {
            bool isBit = true;
            OperateResult<List<byte[]>> operateResult = BuildReadCommand(address, length, isBit = true, splits);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool[]>(operateResult);
            }
            List<bool> list = new List<bool>();
            for (int i = 0; i < operateResult.Content.Count; i++)
            {
                OperateResult<byte[]> operateResult2 = omron.ReadFromCoreServer(operateResult.Content[i]);
                if (!operateResult2.IsSuccess)
                {
                    return OperateResult.CreateFailedResult<bool[]>(operateResult2);
                }
                list.AddRange(operateResult2.Content.Select((byte m) => m != 0));
            }
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        public static OperateResult Write(IReadWriteDevice omron, string address, bool[] values)
        {
            OperateResult<byte[]> operateResult = BuildWriteWordCommand(address, values.Select((bool m) => (byte)(m ? 1 : 0)).ToArray(), isBit: true);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = omron.ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return OperateResult.CreateSuccessResult();
        }

        //[AsyncStateMachine(typeof(<ReadBoolAsync>d__11))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<bool[]>> ReadBoolAsync(IReadWriteDevice omron, string address, ushort length, int splits)
        //{
        //    <ReadBoolAsync>d__11 stateMachine = new <ReadBoolAsync>d__11();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<bool[]>>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.splits = splits;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__12))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IReadWriteDevice omron, string address, bool[] values)
        //{
        //    <WriteAsync>d__12 stateMachine = new <WriteAsync>d__12();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.address = address;
        //    stateMachine.values = values;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Run(IReadWriteDevice omron)
        {
            return omron.ReadFromCoreServer(new byte[5]
		{
			4,
			1,
			255,
			255,
			4
		});
        }

        //[AsyncStateMachine(typeof(<RunAsync>d__14))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> RunAsync(IReadWriteDevice omron)
        //{
        //    <RunAsync>d__14 stateMachine = new <RunAsync>d__14();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Stop(IReadWriteDevice omron)
        {
            return omron.ReadFromCoreServer(new byte[4]
		{
			4,
			2,
			255,
			255
		});
        }

        //[AsyncStateMachine(typeof(<StopAsync>d__16))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> StopAsync(IReadWriteDevice omron)
        //{
        //    <StopAsync>d__16 stateMachine = new <StopAsync>d__16();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult<OmronCpuUnitData> ReadCpuUnitData(IReadWriteDevice omron)
        {
            return omron.ReadFromCoreServer(new byte[3]
		{
			5,
			1,
			0
		}).Then((byte[] m) => OperateResult.CreateSuccessResult(new OmronCpuUnitData(m)));
        }

        //[AsyncStateMachine(typeof(<ReadCpuUnitDataAsync>d__18))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<OmronCpuUnitData>> ReadCpuUnitDataAsync(IReadWriteDevice omron)
        //{
        //    <ReadCpuUnitDataAsync>d__18 stateMachine = new <ReadCpuUnitDataAsync>d__18();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<OmronCpuUnitData>>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult<OmronCpuUnitStatus> ReadCpuUnitStatus(IReadWriteDevice omron)
        {
            return omron.ReadFromCoreServer(new byte[2]
		{
			6,
			1
		}).Then((byte[] m) => OperateResult.CreateSuccessResult(new OmronCpuUnitStatus(m)));
        }

        //[AsyncStateMachine(typeof(<ReadCpuUnitStatusAsync>d__20))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<OmronCpuUnitStatus>> ReadCpuUnitStatusAsync(IReadWriteDevice omron)
        //{
        //    <ReadCpuUnitStatusAsync>d__20 stateMachine = new <ReadCpuUnitStatusAsync>d__20();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<OmronCpuUnitStatus>>.Create();
        //    stateMachine.omron = omron;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}
    }
}
